package ch14
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.Point;

	import utils.Segment;

	/**
	 * 余弦定律
	 * @author sjp
	 *
	 */
	public class Cosines extends Sprite
	{
		private var segment0:Segment;
		private var segment1:Segment;

		public function Cosines()
		{
			init();
		}

		private function init():void
		{
			segment0 = new Segment(100, 20, 0xFF0000);
			addChild(segment0);
			segment1 = new Segment(100, 20);
			addChild(segment1);
			segment1.x = stage.stageWidth / 2;
			segment1.y = stage.stageHeight / 2;
			addEventListener(Event.ENTER_FRAME, onEnterFrame);
		}

		private function onEnterFrame(event:Event):void
		{
			/**
			 * 下面是这个过程：
			 * 1. 获得 segment1 到鼠标的距离。
			 * 2. 获得三条边的长度。 a, b 边很简单。它们都等于 100，因为这就是我们创建关节时所给的长度。
			 * （大家可以删掉 100 这个数，让代码变得更加动态；这里我只是为了简洁。）
			 *  c 边等于距离或 a + b 中最小的值。这是因为三角形中的一条边不能大于其它两条边之和。
			 *  如果不相信，请试着画出一个这样的图形。如果从固定端到鼠标的距离是 200，而两个关节的长度加起来只有 120，
			 *  就不能使用距离作为边长。
			 * 3. 使用余弦定理计算出角 B 和 C，再用 Math.atan2 计算出角 D。角 E，如同我们前面提到的，
			 *  它等于 D + B + 180 + C。当然，在代码中要用 Math.PI 弧度代替 180。
			 * 4. 将 D + B 角转换为角度制，就得到了 seg1 的 rotation。接着计算出 seg1 的末端，
			 *  并将 seg0 放置在此。
			 * 5. 最后，seg0 的 rotation 等于角 E，转换为角度制。
			 *
			 * 具体见 P247 图
			 * */
			var dx:Number = mouseX - segment1.x;
			var dy:Number = mouseY - segment1.y;
			var dist:Number = Math.sqrt(dx * dx + dy * dy);
			var a:Number = 100;
			var b:Number = 100;
			//三角中，两边之和 > 第三边
			var c:Number = Math.min(dist, a + b);
			var B:Number = Math.acos((b * b - a * a - c * c) / (-2 * a * c));
			var C:Number = Math.acos((c * c - a * a - b * b) / (-2 * a * b));
			var D:Number = Math.atan2(dy, dx);
			/**
			 * 大家也许注意到了连接处永远只向一个方向弯曲。
			 * 这对于要建立一个肘部或膝关节也许是件好事，因为它们只能向一个方向弯曲。
			 * 当我们要可以特意计算出这样的角度时，那么这个问题就有两种解决方法：
			 * 向一个方向弯曲，或向另一个方向弯曲。我们已经计算过一个方向的弯曲，通过加 D 和 B，再加 C 来完成。
			 * 如果将它们全部减去，效果相同，但是手臂的弯曲方向是相反的。
			 * */
			var E:Number = D + B + Math.PI + C;
			segment1.rotation = (D + B) * 180 / Math.PI;
//			var E:Number = D - B + Math.PI - C;
//			segment1.rotation = (D - B) * 180 / Math.PI;
			segment0.x = segment1.getPin().x;
			segment0.y = segment1.getPin().y;
			segment0.rotation = E * 180 / Math.PI;
		}
	}
}